home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MAIL.SWG / 0011_Reading QWK Files.pas < prev    next >
Pascal/Delphi Source File  |  1993-11-02  |  5KB  |  155 lines

  1. {
  2. WILLIAM MCBRINE
  3.  
  4. >I have this File here that tells me the format of QWK stuff, and it
  5. >says that the messages.dat File is a whole bunch of Strings of length 128...
  6.  
  7. This is wrong. They aren't Pascal Strings, simply 128-Byte blocks.
  8. Within the Text blocks, each line is terminated by a "pi" Character
  9. ($E3).
  10.  
  11. >I dont know if I did this right but what I load the data into is
  12. >this:  (I have an Array[1..100] of messagedata).
  13.  
  14. >Type
  15. >  MessageData = Record
  16. >    Rec : String[128];
  17. >  end;
  18.  
  19. For blocks of Text, you want someting like this:
  20.  
  21. Type
  22.   messagedata = Array[0..127] of Char;
  23.  
  24. For the message HEADER, you need something more complex. Here's the
  25. structure I use in my QWK door:
  26. }
  27. qwkhead = Record
  28.   status   : Char;
  29.   messnum  : Array [1..7] of Char;
  30.   date     : Record
  31.     month : Array [1..2] of Char;
  32.     dash1 : Char;
  33.     day   : Array [1..2] of Char;
  34.     dash2 : Char;
  35.     year  : Array [1..2] of Char
  36.   end;
  37.   time     : Record
  38.     hour   : Array [1..2] of Char;
  39.     colon  : Char;
  40.     minute : Array [1..2] of Char
  41.   end;
  42.   toname   : Array [1..25] of Char;
  43.   from     : Array [1..25] of Char;
  44.   subject  : Array [1..25] of Char;
  45.   passwd   : Array [1..12] of Char;
  46.   refnum   : Array [1..8] of Char;
  47.   length   : Array [1..6] of Char;
  48.   killflag : Byte;
  49.   confnum  : Word;
  50.   null     : Word;
  51.   nettag   : Char
  52. end;
  53.  
  54. {
  55. This is also 128 Bytes.
  56.  
  57. >1).  A tiny little thing that's not too important right now, but it's
  58. >bugging me.  When I try to load the first Record (which is supposed
  59. >to be a packet header) from messages.dat, I seem to be not reading in
  60. >the first Character... Like, Constantly it'll skip the first
  61. >Character... it'll say "roduced by Qmail..." instead of "Produced by
  62. >Qmail..."
  63.  
  64. The first Character is going into the length field of the String.
  65. Position [0] of the String contains the length.
  66.  
  67. Your "problem 2" is the same thing. 128 Bytes are actually read, but
  68. only the erroneous length's worth of them are printed out.
  69.  
  70. Here's some pseudocode to read a whole packet:
  71.  
  72.  Open MESSAGES.DAT
  73.  Skip the first Record (128 Bytes)
  74.  While not EOF do
  75.   begin
  76.    Read a message header
  77.    Get length of Text in blocks from qwkhead.length (in ASCII) -1
  78.    Reserve memory For 128 Bytes*number of blocks
  79.    Read Text blocks
  80.    Parse Text
  81.    Release memory
  82.   end
  83.  Close MESSAGES.DAT, cleanup
  84.  
  85. "Parse Text" is the hard part. I wrote an Asm routine to convert the
  86. pi-delimited Text into Strings, pointed to by an Array of Pointers.
  87. (This is the format used by the Searchlight Programmer's Library message
  88. routines; pretty easy to work With.) Pointer "a" points to this:
  89.  
  90.  msgType = Record
  91.             msglen:Word;
  92.             msglin:Array[1..400] of Pointer
  93.            end;
  94.  
  95. The "raw data" (Pointer b) below starts one Byte before the actual QWK
  96. data. The purpose of this is to hold the first String length after
  97. conversion. "d" should be the maximum number of lines to convert (400,
  98. in this case); "e" should be about 79 (though it can be set all the way
  99. up to 255 if desired).
  100. }
  101.  
  102. Procedure mangle(a, b : Pointer; c, d, e : Word); Assembler;
  103. Asm
  104.   push ds
  105.   mov  ax,c           {# of blocks loaded (maximum length)}
  106.   les  di,b           {raw data; lines terminated With pi Chars}
  107.   lds  si,a           {msgType: Word:linecount, 1..400:Pointers}
  108.   xor  bx,bx          {line count=0}
  109.   inc  si             {to first line Pointer}
  110.   inc  si
  111.   mov  dx,di
  112.   mov  cl,7
  113.   shl  ax,cl          {blocks * 128 = maximum Bytes in message}
  114.   mov  cx,ax
  115.   cld
  116.  @mloop:
  117.   push  ax
  118.   inc   di
  119.   mov   al, $E3       {pi Character; QWK packet line delimiter}
  120.   repnz scasb         {find one}
  121.   pop   ax            {ax = length before search, cx = length left}
  122.   jnz   @notfound     {if there aren't any, done With message}
  123.   sub   ax, cx
  124.   dec   ax            {length of line}
  125.   cmp   ax, e
  126.   jle   @placelen
  127.   mov   ax, e         {limit line length}
  128.  @placelen:
  129.   xchg  di, dx        {beginning of String in raw data}
  130.   seges mov [di], al  {wow, now it's a Pascal String!}
  131.   mov   [si], di
  132.   mov   [si+2], es
  133.   add   si, 4         {set the Pointer to it}
  134.   dec   dx            {DX was at $E3 + 1}
  135.   mov   di, dx
  136.   mov   ax, cx
  137.   inc   bx
  138.   cmp   bx, d         {maximum number of lines}
  139.   jle   @mloop        {start next line/String}
  140.  @notfound:
  141.   lds   si, a         {line counter in msgType}
  142.   mov   [si], bx      {store # of lines}
  143.   pop   ds            {magically a message!}
  144. end;
  145.  
  146. {then, to print this Text, you'd do something like this: }
  147.  
  148. Procedure dump;
  149. Var
  150.   i : Word;
  151. begin
  152.   For i := 1 to a^.msglen do
  153.     Writeln(a^.msglin[i]^);
  154. end;
  155.